'''
Created on Jun 6, 2009

@author: mkiyer
'''

import os
import sys
import subprocess

from veggie.sample import sampledb
from veggie.app.chipseq.peakfinder import PeakFinder

class ERANGE(PeakFinder):
    '''
    ERANGE ChIP-seq peak detection application

    usage: python $ERANGEPATH/findall.py label samplerdsfile regionoutfile
    [-control controlrdsfile] [-minimum minHits] [-ratio minRatio]
    [-spacing maxSpacing] [-listPeak] [-shift #bp | learn] [-noshift]
    [-autoshift] [-reportshift] [-nomulti] [-raw] [-minPlus fraction]
    [-maxPlus fraction] [-leftPlus fraction] [-minPeak RPM]
    [-revbackground] [-pvalue self|back|none] [-nodirectionality]
    [-trimvalue percent] [-notrim] [-cache pages] [-log altlogfile]
    '''
    _exec_path = os.path.join('$HOME', 'sw', 'chipseq', 'ERANGE')
    _executable = "python " + os.path.join(_exec_path, 'findall.py')

    def _getResultPaths(self):
        return {}
    
    def _makeRDSFromEland(self, label, flowcell, lane, pair, optionstr=None):
        ''' 
        ERANGE requires a special type of file called an RDS file and
        provides script to generate RDS files from ELAND files.  We 
        must prepare the RDS files here before running ERANGE

        python makerdsfromeland2.py label infilename outrdsfile [-append] [-RNA ucscGeneModels] 
        [propertyName::propertyValue] [-index] [-paired 1 or 2] [-extended] [-verbose] 
        [-olddelimiter] [-maxlines num] [-cache numPages]
        '''
        rds_infilename = sampledb.get_sample_data_path(flowcell, lane, pair, format='eland_multi')
        rds_outrdsfile = os.path.join(self.cwd, label + '.rds')

        if os.path.isfile(rds_outrdsfile):
            print >>sys.stderr, "rds file already exists, skipping", rds_outrdsfile
            return rds_outrdsfile

        rds_args = ['python ' + os.path.join(self._exec_path, 'makerdsfromeland2.py'),
                    label,
                    rds_infilename,
                    rds_outrdsfile]
        if pair:
            rds_args.append('-paired ' + str(pair))    
        if optionstr:
            rds_args.append(optionstr)
        argstr = ' '.join(rds_args)
        
        try:
            retcode = subprocess.call(argstr, stdout=self._stdout, stderr=self._stderr, shell=True, cwd=self._cwd)
            if retcode < 0:
                print >>sys.stderr, "Child was terminated by signal", -retcode
            else:
                print >>sys.stderr, "Child returned", retcode
        except OSError, e:
            print >>sys.stderr, "Execution failed:", e
        # TODO: handles error in the subprocess
        return rds_outrdsfile
    
    
    def setUp(self, treatment_name, treatments, control_name=None, controls=None, options=None, cwd=None):
        '''
        see PeakFinder documentation for details
        '''
        if not cwd:
            self.cwd = os.getcwd()

        if (len(treatments) > 1) or (controls and len(controls) > 1):
            print sys.stderr, "warning: ERANGE does not support multiple samples yet"

        exper_name = self._getExperName(treatment_name, control_name)
        for sample in treatments:
            # unpack sample info
            flowcell, lane, pair, format = sample[0], sample[1], sample[2], sample[3]
            # TODO: support different file formats (currently eland_multi only)
            t_path = self._makeRDSFromEland(exper_name, flowcell, lane, pair)
        # if control is present retrieve control data
        if control_name and controls:
            for sample in controls:
                # unpack sample info
                flowcell, lane, pair, format = sample[0], sample[1], sample[2], sample[3]
                # TODO: support different file formats (currently eland_multi only)
                c_path = self._makeRDSFromEland(exper_name, flowcell, lane, pair)
            self.addOption('-control', c_path)

        logfile = exper_name + '_log.txt'
        self.addOption('-log', logfile)
        regionoutfile = exper_name + '_peaks.txt'
        self.args = [exper_name, t_path, regionoutfile]
        # add user-defined options
        if options:
            self.addOptions(options)        
        # write command line to file
        self._writeCommandLine(exper_name + '.commandline')

    def tearDown(self):
        '''
        app-specific post-processing and cleanup code
        '''
        pass